package com.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

/**
 * Copyright © 2016年 author. All rights reserved.
 *
 * @Author 临江仙 hzqiuxm@163.com
 * @Date 2017/9/6 0006 15:11
 */
@Configuration
//@EnableWebSecurity(debug = true)
@EnableWebSecurity
/**
 * http请求URL相关配置：
 * 需要拦截的，不需要拦截的，登录行为控制
 */
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{


    //注入一个角色层级关系类，设置角色的层级关系,Secyrity会自动识别判断角色层级关系
    @Bean
    RoleHierarchy createRoleHierarchy(){
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_USER > ROLE_GUEST ROLE_ADMIN > ROLE_USER");

        return roleHierarchy;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        http.authorizeRequests().antMatchers("/**/*.html").permitAll();
        http.authorizeRequests().antMatchers("/**/*.js").permitAll();
        http.authorizeRequests().antMatchers("/**/*.css").permitAll();
        http.authorizeRequests().antMatchers("/**/*.jpg").permitAll();
        http.authorizeRequests().antMatchers("/**/*.png").permitAll();
        http.authorizeRequests().antMatchers("/**/*.gif").permitAll();

        http.headers().contentTypeOptions().disable();
        http.headers().addHeaderWriter(((request, response) -> response.addHeader("root-name","hzqiuxm")));
        http.csrf().disable();

        http.authorizeRequests().antMatchers("/guest").hasRole("GUEST");
        http.authorizeRequests().antMatchers("/user").hasRole("USER");
        http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN");



//        http.authorizeRequests().antMatchers("/**/*.gif").authenticated()

        http
                .authorizeRequests()
                .antMatchers("*/","/login","/*","/sys/login","/sys/logout").permitAll()//1根路径和/login路径不拦截
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login") //2登陆页面
                .defaultSuccessUrl("/ok") //3登陆成功转向该页面
                .permitAll()
                .and()
                .logout()//退出
                .permitAll();//不用认证


//        http.authorizeRequests().anyRequest().access("authenticated");//需要认证
//        http.authorizeRequests().anyRequest().authenticated();//和上一行作用一致，写法不同而已
//        http.authorizeRequests().antMatchers(HttpMethod.GET).permitAll();//所有的GET方法都不验证
//        http.authorizeRequests().antMatchers("/**").permitAll();//所有的请求都不用去验证


        http.authorizeRequests().mvcMatchers("/home").permitAll();
//        http.authorizeRequests().mvcMatchers(HttpMethod.POST,"/home");
//        http.authorizeRequests().mvcMatchers(HttpMethod.POST,"/home").servletPath("").hasRole("USER");

        //实现自定义匹配
//        http.authorizeRequests().requestMatchers(new RequestMatcher() {
//            @Override
//            public boolean matches(HttpServletRequest request) {
//                return "1".equals(request.getParameter("type"));
//            }
//        }).permitAll();

/*        http.formLogin()
                .loginPage("哪个登录页面")
                .loginProcessingUrl("登录后请求访问的URL")
                .failureUrl("登录失败的页面")//重定向方式，无法获取失败原因，还有一种forWard方式可以获取
//                .failureForwardUrl("登录失败的页面")//可以指向登录页面，加上错误提示
                .defaultSuccessUrl("登录成功的页面")//如果直接访问登录页面，则登录成功后重定向到这个页面
//                .defaultSuccessUrl("登录成功页面",true)//登录成功后，直接重定向到这个页面
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                        //登录成功后就会执行该方法
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
                        //登录失败后执行的方法
                    }
                })
                .permitAll();*/


/*        http.logout()
                .logoutUrl("自定义路径")
                .clearAuthentication(true)
                .addLogoutHandler(((request, response, authentication) -> {
                    System.out.println("=====1=====");
                }))
                .logoutSuccessHandler(((request, response, authentication) -> {
                    response.sendRedirect("重定向路径");
                }))
                .deleteCookies()
                .logoutSuccessUrl("")
                .logoutRequestMatcher(new AntPathRequestMatcher("URL","HttpMethod.GET"))//本来CSRF开启后是只支持POST的，如果要开启GET这样做
                .invalidateHttpSession(true);*/


    }

    @Override
    /**
     * 认证授权类配置：
     * 配置用户，密码，角色
     */
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    		auth
                .inMemoryAuthentication()
                .withUser("qiuxm").password("qiuxm").roles("USER")
                .and()
                .withUser("zhangshan").password("zhangshan").accountLocked(true).roles("USER")
                .and()
                .withUser("lisi").password("lisi").accountExpired(true).roles("USER")
                .and()
                .withUser("hzqiuxm").password("hzqiuxm").roles("USER","ADMIN");

        auth.inMemoryAuthentication().withUser("guest").password("123").roles("GUEST");
        auth.inMemoryAuthentication().withUser("user").password("123").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("123").roles("ADMIN");

//        auth.jdbcAuthentication().dataSource();
    }

    @Override
    /**
     * WEB请求类配置：
     * 忽略静态资源的拦截
     */
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/static/**");

    }

}